home *** CD-ROM | disk | FTP | other *** search
/ CICA 1993 April / CICA MS Windows - April 1993.iso / unzipped / util / mews11 / mswemacs.c < prev    next >
C/C++ Source or Header  |  1992-07-26  |  17KB  |  530 lines

  1. /* The routines in this file provide extra emacs functions available
  2.    under the Microsoft Windows environment on an IBM-PC or compatible
  3.    computer. The following functions are supplied: cutregion,
  4.    clipregion, insertclip and helpengine.
  5.    Also implemented here is the support for scroll bars
  6.  
  7.    Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions
  8.  
  9.    It should not be compiled if the WINDOW_MSWIN symbol is not set */
  10.  
  11. #include    "estruct.h"
  12. #include    <stdio.h>
  13. #include    "eproto.h"
  14. #include    "edef.h"
  15. #include    "elang.h"
  16.  
  17. #include    "mswin.h"
  18.  
  19. #include    "mswmenu.h"
  20. /* to invoke the commands corresponding to scroll bar actions */
  21.  
  22. #define MAXSCROLL 32767 /* maximum position for scrollbars */
  23.  
  24. static HANDLE   hClipData = NULL;   /* used by insertclip and
  25.                        ClipboardCleanup */
  26.  
  27. /* CopyToClipboard: internal function to copy region to clipboard */
  28. /* ===============                                                */
  29.  
  30. static BOOL PASCAL CopyToClipboard (REGION *Region)
  31. {
  32.     long    Size = 0L;
  33.     HANDLE  hData;
  34. #if WINDOW_MSWIN32
  35.     char    *Data;
  36. #else
  37.     char huge *Data;
  38. #endif
  39.     BOOL    Result = TRUE;
  40.     register LINE *lp;
  41.     register int Offset;
  42.     register int lcnt;       /* used to reduce longop() overhead */
  43.     
  44.     /*-figure out the size of the clipboard data (end of lines have to
  45.        be turned into CR-LF) */
  46.     Size = Region->r_size;
  47.     if (curwp->w_dotp != curwp->w_markp[0]) {   /* multiple lines */
  48.         lp = Region->r_linep;
  49.         do {
  50.             ++Size;
  51.         lp = lforw(lp);
  52.     } while ((lp != curwp->w_dotp) && (lp != curwp->w_markp[0]));
  53.     }
  54.     if (Size == 0L) return TRUE;
  55.  
  56.     /*-copy the buffer data into a block of global memory */
  57.     if (hData = GlobalAlloc (GMEM_MOVEABLE, Size + 1)) {
  58.         if (!(Data = GlobalLock (hData))) goto NoClipboardMemory;
  59.     lp = Region->r_linep;
  60.     Offset = Region->r_offset;
  61.     lcnt = 0;
  62.     while (Size-- > 0) {
  63.         if (Offset != llength(lp)) {    /* middle of line */
  64.             *Data++ = lgetc(lp, Offset);
  65.             ++Offset;
  66.         }
  67.         else {                          /* end of line */
  68.             *Data++ = '\r';
  69.             *Data++ = '\n';
  70.             Size--;
  71.             lp = lforw(lp);
  72.             Offset = 0;
  73.             if (--lcnt < 0) {
  74.             longop (TRUE);
  75.             lcnt = 10;  /* reduce longop calls overhead */
  76.         }
  77.         }
  78.     }
  79.     *Data = '\0';
  80.     /*-pass the text to the clipboard */
  81.     GlobalUnlock (hData);
  82.     if (OpenClipboard (hFrameWnd)) {
  83.         if (EmptyClipboard ()) {
  84.             SetClipboardData (CF_TEXT, hData);
  85.         }
  86.         else Result = FALSE;
  87.         CloseClipboard ();
  88.     }
  89.     else Result = FALSE;
  90.     if (Result == FALSE) GlobalFree (hData);
  91.     }
  92.     else {
  93. NoClipboardMemory:
  94.     mlabort (TEXT94);   /* out of memory */
  95.         Result = FALSE;
  96.     }
  97.     return Result;
  98. } /* CopyToClipboard */
  99.  
  100. /* cutregion:   move the current region to the clipboard */
  101. /* =========                                             */
  102.  
  103. PASCAL cutregion (int f, int n)
  104. {
  105.     REGION  Region;
  106.     int     Result;
  107.  
  108.     /*-don't allow command if read-only mode */
  109.     if (curbp->b_mode & MDVIEW) return rdonly();
  110.  
  111.     if ((Result = getregion (&Region)) != TRUE) return Result;
  112.  
  113.     if ((Result = CopyToClipboard (&Region)) != TRUE) return Result;
  114.     curwp->w_dotp = Region.r_linep;
  115.     curwp->w_doto = Region.r_offset;
  116.     return ldelete (Region.r_size, FALSE);
  117. } /* cutregion */
  118.  
  119. /* clipregion:  copy the current region into the clipboard */
  120. /* ==========                                              */
  121.  
  122. PASCAL clipregion (int f, int n)
  123. {
  124.     REGION  Region;
  125.     int     Result;
  126.     
  127.     if ((Result = getregion (&Region)) != TRUE) return Result;
  128.  
  129.     return CopyToClipboard (&Region);
  130. } /* clipregion */
  131.  
  132. /* insertclip:  insert the clipboard contents at dot */
  133. /* ==========                                        */
  134.  
  135. PASCAL insertclip (int f, int n)
  136. {
  137.     BOOL    Result = TRUE;
  138.     char    *Text, *TextHead;
  139.     short int curoff;
  140.     LINE    *curline;
  141.  
  142.     /*-don't allow command if read-only mode */
  143.     if (curbp->b_mode & MDVIEW) return rdonly();
  144.  
  145.     if (OpenClipboard (hFrameWnd)) {
  146.     if ((hClipData = GetClipboardData (CF_TEXT)) != NULL) {
  147.         /* Save the local pointers to hold global "." */
  148.         if (yankflag == SRBEGIN) {
  149.         /* Find the *previous* line, since the line we are on
  150.            may disappear due to re-allocation.  This works even
  151.            if we are on the first line of the file. */
  152.         curline = lback(curwp->w_dotp);
  153.         curoff = curwp->w_doto;
  154.         }
  155.         if ((TextHead = GlobalLock (hClipData)) != NULL) {
  156.         while (n--) {
  157.             Text = TextHead;
  158.             while (*Text != '\0') {
  159.             if (*Text == '\n') {
  160.                 if (lnewline () == FALSE) {
  161.                 Result = FALSE;
  162.                 goto bail_out;
  163.                 }
  164.             }
  165.             else {
  166.                 if (*Text != '\r') if (linsert (1, *Text) == FALSE) {
  167.                 Result = FALSE;
  168.                 goto bail_out;
  169.                 }
  170.             }
  171.             ++Text;
  172.             }
  173.         }
  174. bail_out:
  175.                 GlobalUnlock (hClipData);
  176.                 hClipData = NULL;   /* for ClipboardCleanup */
  177.                 /* If requested, set global "." back to the beginning of
  178.            the yanked text. */
  179.         if (yankflag == SRBEGIN) {
  180.             curwp->w_dotp = lforw(curline);
  181.             curwp->w_doto = curoff;
  182.         }
  183.         }
  184.     }
  185.     else Result = FALSE;
  186.     CloseClipboard ();
  187.     }
  188.     else Result = FALSE;
  189.     return Result;
  190. } /* insertclip */
  191.  
  192. /* ClipboardCleanup:    to be called if the user aborts during a longop */
  193. /* ================                                                     */
  194.  
  195. void FAR PASCAL ClipboardCleanup (void)
  196. {
  197.     if (hClipData) {
  198.         GlobalUnlock (hClipData);
  199.         CloseClipboard ();
  200.     }
  201. } /* ClipboardCleanup */
  202.  
  203. /* helpengine:  invoke the MS-Windows help engine */
  204. /* ==========                                     */
  205.  
  206. PASCAL helpengine (int f, int n)
  207. {
  208.     char    OldHelpFile [NFILEN];
  209.     char    HelpKey [NLINE];
  210.     BOOL    Result;
  211.  
  212.     strcpy (OldHelpFile, HelpEngineFile);
  213.     SetWorkingDir ();
  214.     if ((Result = FILENAMEREPLY (TEXT307, HelpEngineFile, NFILEN)) != TRUE) return Result;
  215.         /* "Help file: " */
  216.     if (HelpEngineFile[0] == '\0') {
  217.         strcpy (HelpEngineFile, OldHelpFile);
  218.         return FALSE;
  219.     }
  220.     else {
  221.         Result = mlreply (TEXT308, HelpKey, NLINE);
  222.     if ((Result != TRUE) && (Result != FALSE)) return Result;
  223.         /* "Help key: " */
  224.     if (HelpKey[0] == '\0') {
  225.         WinHelp (hFrameWnd, HelpEngineFile, HELP_INDEX, NULL);
  226.     }
  227.     else {
  228.         WinHelp (hFrameWnd, HelpEngineFile, HELP_KEY,
  229.                      (DWORD)(LPSTR)&HelpKey[0]);
  230.     }
  231.     }
  232.     return TRUE;
  233. } /* helpengine */
  234.  
  235. /* minimizescreen:  turn the current screen into an icon */
  236. /* ==============                                        */
  237.  
  238. PASCAL  minimizescreen (int f, int n)
  239. {
  240.     BOOL    nq;
  241.  
  242.     nq = notquiescent;
  243.     notquiescent = 0;
  244.     ShowWindow (first_screen->s_drvhandle, SW_MINIMIZE);
  245.     notquiescent = nq;
  246.     return TRUE;
  247. } /* minimizescreen */
  248.  
  249. /* ForceMessage:    do a SendMessage, forcing quiescent mode */
  250. /* ============                                              */
  251.  
  252. static PASCAL ForceMessage (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  253. {
  254.     BOOL    nq;
  255.  
  256.     nq = notquiescent;
  257.     notquiescent = 0;
  258.     SendMessage (hWnd, wMsg, wParam, lParam);
  259.     notquiescent = nq;
  260. } /* ForceMessage */
  261.  
  262. /* maximizescreen:  maximize the current screen */
  263. /* ==============                               */
  264.  
  265. PASCAL  maximizescreen (int f, int n)
  266. {
  267.     ForceMessage (hMDIClientWnd, WM_MDIMAXIMIZE,
  268.                   (UINT)first_screen->s_drvhandle, 0L);
  269.     return TRUE;
  270. } /* maximizescreen */
  271.  
  272. /* restorescreen:   restore the current screen from maximized/minimized state */
  273. /* =============                                                              */
  274.  
  275. PASCAL  restorescreen (int f, int n)
  276. {
  277.     ForceMessage (hMDIClientWnd, WM_MDIRESTORE,
  278.                   (UINT)first_screen->s_drvhandle, 0L);
  279.     return TRUE;
  280. } /* restorescreen */
  281.  
  282. /* tilescreens: tile the non-iconized screens */
  283. /* ===========                                */
  284.  
  285. PASCAL  tilescreens (int f, int n)
  286.  
  287. /* without a numeric argument, tile horizontally. With a numeric argument
  288.    of 1, tile vertically */
  289. {
  290.     if (f && (n == 1)) {
  291.         ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_HORIZONTAL, 0L);
  292.     }
  293.     else ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_VERTICAL, 0L);
  294.     return TRUE;
  295. } /* tilescreens */
  296.  
  297. /* cascadescreens:  position the non-iconized screens in cascade */
  298. /* ==============                                                */
  299.  
  300. PASCAL  cascadescreens (int f, int n)
  301. {
  302.     ForceMessage (hMDIClientWnd, WM_MDICASCADE, 0, 0L);
  303.     return TRUE;
  304. } /* cascadescreens */
  305.  
  306. /* renamescreen:    change the current screen's name */
  307. /* ============                                      */
  308.  
  309. PASCAL  renamescreen (int f, int n)
  310. {
  311.     char    scr_name[NSTRING];  /* buffer to hold screen name */
  312.     int     result;
  313.  
  314.     /* get the new name of the screen */
  315.     if ((result = mlreply(TEXT335, scr_name, NSTRING)) != TRUE) {
  316.     /* "Change screen name to: " */
  317.     return result;
  318.     } 
  319.     if (lookup_screen(scr_name) != (SCREEN*)NULL) {
  320.     mlwrite (TEXT336);  /* "[Screen name already in use]" */
  321.     return FALSE;
  322.     }
  323.  
  324.     free (first_screen->s_screen_name);
  325.     first_screen->s_screen_name = copystr (scr_name);
  326.     SetWindowText (first_screen->s_drvhandle, scr_name);
  327.     return TRUE;
  328. } /* renamescreen */
  329.  
  330. /* ScrollMessage:   handle WM_HSCROLL and WM_VSCROLL */
  331. /* =============                                     */
  332. void FAR PASCAL ScrollMessage (HWND hWnd, UINT wMsg, WORD ScrlCode, int Pos)
  333.  
  334. {
  335.     int     Delta;
  336.     
  337.     if (notquiescent) return;
  338.     
  339.     if (wMsg == WM_VSCROLL) {
  340.         switch (ScrlCode) {
  341.             case SB_LINEUP:
  342.                 mvupwind (FALSE, 1);
  343.                 break;
  344.             case SB_LINEDOWN:
  345.                 mvdnwind (FALSE, 1);
  346.                 break;
  347.             case SB_PAGEUP:
  348.                 backpage (FALSE, 1);
  349.                 break;
  350.             case SB_PAGEDOWN:
  351.                 forwpage (FALSE, 1);
  352.                 break;
  353.             case SB_THUMBTRACK:
  354.             case SB_THUMBPOSITION:
  355.                 if (Win31API) {
  356.                     if (ScrlCode == SB_THUMBPOSITION) return;
  357.                 }
  358.                 else {
  359.                     if (ScrlCode == SB_THUMBTRACK) return;
  360.                     /* there is something wrong with thumb tracking in
  361.                        Windows 3.0 */
  362.                 }
  363.                 Delta = Pos - GetScrollPos (hWnd, SB_VERT);
  364.                 if (Delta) mvdnwind (TRUE, Delta);
  365.                 break;
  366.             default:
  367.                 return;
  368.         }
  369.         curwp->w_flag |= WFMODE;
  370.     }
  371.     else {
  372.         switch (ScrlCode) {
  373.             case SB_LINEUP:
  374.                 Delta = -1;
  375.                 break;
  376.             case SB_LINEDOWN:
  377.                 Delta = 1;
  378.                 break;
  379.             case SB_PAGEUP:
  380.                 Delta = -term.t_ncol;
  381.                 break;
  382.             case SB_PAGEDOWN:
  383.                 Delta = term.t_ncol;
  384.                 break;
  385.             case SB_THUMBTRACK:
  386.                 Delta = Pos - GetScrollPos (hWnd, SB_HORZ);
  387.                 break;
  388.             default:
  389.                 return;
  390.         }
  391.         curwp->w_fcol += Delta;
  392.         if (curwp->w_fcol < 0) curwp->w_fcol = 0;
  393.         if (curwp->w_doto < curwp->w_fcol) {
  394.             /* reframe dot if it was left past the left of the screen */
  395.             curwp->w_doto = min(curwp->w_fcol,llength(curwp->w_dotp));
  396.         }
  397.         if (curwp->w_doto > (curwp->w_fcol + term.t_ncol - 2)) {
  398.             /* reframe dot if it was left past the right of the screen */
  399.             curwp->w_doto = curwp->w_fcol + term.t_ncol - 2;
  400.     }
  401.         curwp->w_flag |= WFMODE | WFHARD;
  402.     }
  403.     if (in_check()) GenerateMenuSeq (IDM_NULLPROC);
  404.         /* this ensures we go through the editloop(), updating the
  405.            modeline display and running the cmdhook, among other things */
  406.     ShowEmacsCaret (FALSE);
  407.     update (TRUE);
  408.     ShowEmacsCaret (TRUE);
  409. } /* ScrollMessage */
  410.  
  411. /* ScrollBars:      shows/hides, enables/disables scroll bars for all screens */
  412. /* ==========                                                                 */
  413. void FAR PASCAL ScrollBars (void)
  414.  
  415. {
  416.     static int VScroll = TRUE;
  417.     static int HScroll = TRUE;
  418.     static int Enabled = TRUE;
  419.     int     Quiescence;
  420.     SCREEN  *sp;
  421.  
  422.     if (vscrollbar) vscrollbar = TRUE;  /* normalize... */
  423.     if (hscrollbar) hscrollbar = TRUE;
  424.     Quiescence = (notquiescent == 0);
  425.  
  426.     for (sp = first_screen; sp != (SCREEN*)NULL; sp = sp->s_next_screen) {
  427.         if (vscrollbar != VScroll) {
  428.             ShowScrollBar ((HWND)sp->s_drvhandle, SB_VERT, vscrollbar);
  429.         }
  430.         if (hscrollbar != HScroll) {
  431.             ShowScrollBar ((HWND)sp->s_drvhandle, SB_HORZ, hscrollbar);
  432.         }
  433. #if !WIN30SDK
  434. #if !WINDOW_MSWIN32 /* ESB_ENABLE/DISABLE_BOTH not defined in
  435.                        July 92 preliminary SDK for Windows NT */
  436.         if ((Enabled != Quiescence) && Win31API && !TakingANap) {
  437.             /* note: no disabling of scroll bars during naps (i.e. fence
  438.                matching), to avoid annoying blinking */
  439.             EnableScrollBar ((HWND)sp->s_drvhandle, SB_BOTH,
  440.                              Quiescence ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
  441.     }
  442. #endif
  443. #endif
  444.     }
  445.  
  446.     if ((Enabled != Quiescence) && Win31API && !TakingANap) {
  447.         Enabled = Quiescence;
  448.     }
  449.     VScroll = vscrollbar;
  450.     HScroll = hscrollbar;
  451. } /* ScrollBars */
  452.  
  453. /* updscrollbars:      updates the scroll bars for a screen */
  454. /* =============                                            */
  455. PASCAL  updscrollbars (SCREEN *sp, char w_flag)
  456.  
  457. /* the w_flag is used to determine what needs updating: if the WFHARD
  458.    bit is set, both scroll bars need an update. If the WFMOVE bit
  459.    is set, the horizontal scroll bar needs an update */
  460. /* this function assumes s_cur_window matches curwp for the first_screen */
  461. {
  462.     int ScrollMax, ScrollMin, ScrollPos;
  463.     
  464.     if (vscrollbar && (w_flag & WFHARD)) {
  465.         int    lastline;
  466.         int     topline;
  467.  
  468.         {   /*-figure-out where we are at vertically */
  469.             register LINE   *lp;
  470.             register LINE   *linep; /* header (= last) line of buffer */
  471.             LINE    *toplp;         /* top line of window */
  472.  
  473.             linep = sp->s_cur_window->w_bufp->b_linep;
  474.             toplp = sp->s_cur_window->w_linep;
  475.             topline = lastline = 0;
  476.             lp = linep;
  477.             do {
  478.                 lp = lforw(lp);
  479.                 lastline++;
  480.                 if (lp == toplp) topline = lastline;
  481.             } while (lp != linep);
  482.         }
  483.         lastline += 1 - sp->s_cur_window->w_ntrows;
  484.         if (lastline <= 1) lastline = 2;    /* to avoid scrollbar hiding */
  485.         lastline = min(lastline, MAXSCROLL);
  486.         topline = min(topline, MAXSCROLL);
  487.         GetScrollRange ((HWND)sp->s_drvhandle, SB_VERT,
  488.                         &ScrollMin, &ScrollMax);
  489.         if ((ScrollMax != lastline) || (ScrollMin != 1)) {
  490.             SetScrollRange ((HWND)sp->s_drvhandle, SB_VERT, 1,
  491.                             lastline, FALSE);
  492.             ScrollPos = -1; /* makes sure the scroll display is updated */
  493.         }
  494.         else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_VERT);
  495.         if (topline != ScrollPos) {
  496.             SetScrollPos ((HWND)sp->s_drvhandle, SB_VERT,
  497.                           topline, TRUE);
  498.         }
  499.     }
  500.     if (hscrollbar && (w_flag & (WFMOVE | WFHARD))) {
  501.         /*-figure-out where we stand horizontally */
  502.         int     row;
  503.         LINE    *lp;
  504.         WINDOW  *wp = sp->s_cur_window;
  505.         int     maxlength = 0;
  506.  
  507.         lp = wp->w_linep;
  508.         for (row = 0; (row < wp->w_ntrows) && (lp != wp->w_bufp->b_linep);
  509.              row++) {
  510.             maxlength = max(maxlength, llength(lp));
  511.             lp = lforw(lp);
  512.         }
  513.         if (maxlength <= 0) maxlength = 1;
  514.         maxlength = min(maxlength, MAXSCROLL);
  515.         row = min(wp->w_fcol, MAXSCROLL);
  516.         GetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ,
  517.                         &ScrollMin, &ScrollMax);
  518.         if ((ScrollMax != maxlength) || (ScrollMin != 0)) {
  519.             SetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ, 0,
  520.                             maxlength, FALSE);
  521.             ScrollPos = -1; /* makes sure the scroll display is updated */
  522.         }
  523.         else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ);
  524.         if (row != ScrollPos) {
  525.             SetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ,
  526.                           row, TRUE);
  527.         }
  528.     }
  529. } /* updscrollbars */
  530.